package MapEditor;

import YottaTron.Map.*;
import YottaTron.*;
import YottaTron.Sprites.ObstacleSprite;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.ArrayList;
import javax.swing.JPanel;

public class MapPanel extends JPanel implements MouseListener, MouseMotionListener, KeyListener {

    MainFrame frame;
    int width, height;
    YottaTron.Map.Map map;
    ArrayList grafickeObjekty;
    public ObstacleSprite activeObject;
    public int tileWidth,  tileHeight;
    int obstacleID = 0;

    /* sirka a vyska mapy, odkaz na hlavni frame
     */
    public MapPanel(int width, int height, MainFrame frame) {
        this.frame = frame;
        this.width = width;
        this.height = height;

        // velikost tiles urcuje hrubost rozmisteni predmetu v mape
        tileWidth = 10;
        tileHeight = 10;

        // pro ukladani objektu v mape
        map = new YottaTron.Map.Map(frame.tfBackground.getText(), Runner.GST_BACKGROUND1, width, height, tileWidth, tileHeight);

        // objekt ktery se bude umistovat do mapy a bude se vykreslovat na miste kuzoru
        // vybere se kliknutim na objekt v objektu tridy MapObjectsMenu, ktery se nachazi ve frame
        activeObject = null;


        this.setPreferredSize(new Dimension(width, height));
        this.addMouseMotionListener(this);
        this.addKeyListener(this);
        this.addMouseListener(this);
        this.repaint();
    } // konec konstruktoru tridy Plocha

    public void umisteni() {
        // umisteni aktivniho herniho prvku do mapy
        int x, y;
        int aktx = (int) activeObject.x;
        int akty = (int) activeObject.y;


        if (activeObject.ID < 1000) {// nejedna se o typ povrchu, ale o objekt
            boolean mistoObsazene = false;

            // zjistovani zda se na miste danem kuzrorem jiz nachazi nejaky objekt
            for (Iterator it = map.obstacles.iterator(); it.hasNext();) {
                Obstacle obstacle = (Obstacle) it.next();
                x = obstacle.x;
                y = obstacle.y;
                if ((aktx + tileWidth > x) && (aktx < x + tileWidth) && (akty + tileHeight > y) && (akty < y + tileHeight)) {
                    mistoObsazene = true;
                }
            }

            System.out.println("misto obsazene " + mistoObsazene);

            if ((aktx >= 0) && (akty >= height - map.height) && !mistoObsazene) {

                // activeObject.ID je v MapObjectsMenu nastaveno na index grafiky v poli staticGraphic
                map.obstacles.add(new Obstacle(aktx, akty, activeObject.ID, obstacleID + 10000));
                obstacleID++;
                System.out.println("pocet objektu: " + map.obstacles.size() +
                        "posledni objekt umisten na x " + aktx + " y " + akty);

                //System.out.println("x: "+ (int)((aktx - levyOkrajMapy)/zoom));
                //System.out.println("y: "+ (int)((height-akty)/zoom));
                //System.out.println("pocet grafiky:" + mapa.objekty.size());
                repaint();
            } // konec umisteni aktivniho herniho prvku do mapy

        } else {// typ povrchu
            map.gameField[aktx / tileWidth][akty / tileHeight + 1] = activeObject.ID - 1000;
        }
    }

    public void smazani() {
        int x, y;
        if (activeObject.ID < 1000) {// nejedna se o typ povrchu, ale o objekt
            for (Iterator it = map.obstacles.iterator(); it.hasNext();) {
                Obstacle o = (Obstacle) it.next();
                // souradnice objektu ulozeneho v mape, se museji prepocitat do souradneho systemu zobrazeni editoru
                x = o.x;
                y = o.y;
                if ((x == (int) activeObject.x) && (y == (int) activeObject.y)) {
                    System.out.println("souhlasi");
                    it.remove();
                    System.out.println(map.obstacles.size());
                }
            }
        } else {// vymazani specialniho typu povrchu.. nastavise na 0 ... volno
            map.gameField[(int) activeObject.x / tileWidth][(int) activeObject.y / tileHeight + 1] = 0;
        }

    }

    public void pohybAktivnihoObjektu(int x, int y) {
        if (activeObject != null) {
            if ((y >= 0) && (y < height) && (x >= 0) && (x < width)) {
                x = x - (int) (x % tileWidth);
                y = y - (int) (y % tileHeight);
            }

            int minx = (int) activeObject.x;
            int miny = (int) activeObject.y;

            activeObject.x = x;
            activeObject.y = y;
            //objekty[drag].vykresli(G, zoom);
            repaint(x, y, activeObject.width, activeObject.height);
            repaint(minx, miny, activeObject.width, activeObject.height);
        }
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        System.out.println("pressed");

        if (activeObject != null) {
            if (e.getButton() == e.BUTTON1) {
                umisteni();
            }
            if (e.getButton() == e.BUTTON3) {
                smazani();
            }
        }
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mouseDragged(MouseEvent e) {
        int m = e.getModifiers();
        int x = e.getX();
        int y = e.getY();

        if (activeObject != null) {
            pohybAktivnihoObjektu(x, y);

            //System.out.println(((m & InputEvent.BUTTON1_MASK) != 0));
            if ((m & InputEvent.BUTTON1_MASK) != 0) {
                umisteni();
                System.out.println("dragovani");
            }
            if ((m & InputEvent.BUTTON3_MASK) != 0) {
                smazani();
            }
        }
    }

    public void mouseMoved(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        if (activeObject != null) {
            pohybAktivnihoObjektu(x, y);
            this.repaint();
        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public void setSize() {
        this.setPreferredSize(new Dimension(width, height));
        map.width = width;
        map.height = height;
        System.out.println("width " + width + ",height " + height);
        repaint();
    }

    public void setZoom(double zoom) {
//        this.zoom = zoom;
//        levyOkrajMapy = (int) (width - map.width * zoom - 3);
//        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        System.out.println("MapPanel repainting");
        Graphics2D g2 = (Graphics2D) g;

        g2.setColor(Color.WHITE);
        g2.fillRect(0, 0, width, height);
        g2.setColor(Color.BLACK);
        g2.drawImage(frame.graphics[map.backgroundGraphics].getImage(0), 0, 0, null);

        //vykresleni mrize podle velikosti tiles
        for (int i = tileWidth; i < map.width; i += tileWidth) {
            g2.drawLine(i, 0, i, map.height);
        }
        for (int i = tileHeight; i < map.height; i += tileHeight) {
            g2.drawLine(0, i, map.width, i);
        }

        // a vykresleni nastaveni jednotlivych policek
        g2.setColor(Color.RED);
        for (int i = 0; i < map.gameField.length; i++) {
            for (int j = 0; j < map.gameField[0].length; j++) {
                if (map.gameField[i][j] > 0) {
                    g2.drawChars(Integer.toString(map.gameField[i][j]).toCharArray(), 0, 1, i * tileWidth, j * tileHeight);
                }
            }
        }


        if (activeObject != null) {
            if (activeObject.ID < 1000) {
                g2.drawImage(activeObject.obstacleGraphic.getImage(0), (int) activeObject.x, (int) activeObject.y, null);
            } else {
                g2.fillRect((int) activeObject.x, (int) activeObject.y, tileWidth, tileHeight);
            }
        }

        for (Iterator it = map.obstacles.iterator(); it.hasNext();) {
            Obstacle o = (Obstacle) it.next();
            g2.drawImage(frame.graphics[o.obstacleGraphics].getImage(0), (int) o.x, (int) o.y, null);

        }


//        g2.setColor(Color.BLACK);
//        g2.fillRect(map.width, 0, width, 5000);
//        g2.fillRect(0, map.height, 5000, height);
    }
}
